#!/usr/local/bin/python
#1 is black 0 is white
haspondered = 0
"""
	This is the interactive ai for chess written entirely by Sam Phippen <samphippen@gmail.com>

 	This file is part of chess.

    chess is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    chess is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with chess.  If not, see <http://www.gnu.org/licenses/>.

"""
__program__ = 'chess ai'
__author__ = 'Sam Phippen <samphippen@gmail.com>'

from random import *
import chess
import string
cols = ['a','b','c','d','e','f','g','h']
rows = ['1','2','3','4','5','6','7','8']
currentopening = -1
mycolour = 1
game = chess.Game(None, None)
board = game.board
permaboard = board
permagame = game
othercolour = 0
#for line in game.show():
	#print line
def testloc(square):
	loc = chess.AlgebraicLoc(square)
	piece = board.get(loc)
	if piece != -1:
		rep = board.asArray()
		return piece.possible(board)
	else:
		return -1	
def sicilianopening():
	global turncount
	print turncount
	if turncount == 0:
		print "first move"
		game.move('Pc7-c5')
		print ('Pc7-c5')
		return 1
	elif turncount == 1:
		loc = chess.AlgebraicLoc('d4')
		piece = board.get(loc)
		if piece != -1:
			game.move('Pc5-d4')
		else:	
			game.move('Pd7-d6')	
		
		return 1
	elif turncount == 2:
		loc = chess.AlgebraicLoc('d4')
		piece = board.get(loc)
		if piece != -1 and colourat('d4') != mycolour:
			game.move('Pc5-d4')
			return 1
		else:
			return 0		
	elif turncount == 3:
		print haspondered
		
		game.move('Pa7-a6')
		return 1
	else:
		return 0		
def colourat(square):
	loc = chess.AlgebraicLoc(square)
	piece = board.get(loc)
	if piece != -1:
		return piece.color
	else:
		return -1	
def threats(square):
	thethreats = []
	loc = chess.AlgebraicLoc(square)
	thethreats = board.threat(loc,mycolour)
	return thethreats			
def defense(square):
	defs = []
	loc = chess.AlgebraicLoc(square)
	defenses = board.threat(loc,othercolour)
	return defenses
							
def mypeicespossible():
	possiblemoves = []
	for i in range(0,8):
		for j in range(0,8):
			square = cols[j] + rows[i]
			if colourat(square) == mycolour:
				loc = chess.AlgebraicLoc(square)
				piece = board.get(loc)
				presymbol = str(piece.symbol[0]) + square
				possiblemoves.append([presymbol,testloc(square)])
	return possiblemoves			
def mypeices():
	locations = []
	for i in range(0,8):
		for j in range(0,8):
			square = cols[j] + rows[i]
			if colourat(square) == mycolour:
				locations.append(square)
	return locations			
currentopening = -1
def opening():
	global haspondered
	print "opening"
	print haspondered
	if haspondered == 1:
		print "return 0"
		return 0
	else:
		pass	
	global openingflag
	flag = openingflag
	print flag
	if turncount <= 4:
		print "turns less than 5"
		if mycolour == 1:
			"i'm black"
			if flag == -1:
				"opening not yet set"
				e4 = chess.AlgebraicLoc('e4')
				d4 = chess.AlgebraicLoc('d4')
				c4 = chess.AlgebraicLoc('c4')
				loc = e4
				piece1 = board.get(loc)
				piece2 = board.get(d4)
				if piece1 != -1:
					flag = 0
					openingflag = flag
				if piece2 != -1:
					flag = 5
					openingflag = flag	
			if flag == 0:
				if sicilianopening() == 1:
					print "sicilian opening"
					game.advance()
					return 1		
				else:
					return 0
			elif flag == 5:
				print "queens gambit opening"
				if queensgambit() == 1:
					game.advance()
					return 1
				else:
					return 0	
			else:
				return 0			
		else:
			if turncount == 0:
				game.move('Pe2-e4')
				game.advance()
				return 1
			if turncount == 1:
				c5 = chess.AlgebraicLoc('c5')
				e6 = chess.AlgebraicLoc('e6')
				e5 = chess.AlgebraicLoc('e5')
				c6 = chess.AlgebraicLoc('c6')
				d5 = chess.AlgebraicLoc('d5')
				g6 = chess.AlgebraicLoc('g6')
				piece1 = board.get(c5)
				piece2 = board.get(e6)
				piece3 = board.get(e5)
				piece4 = board.get(c6)
				piece5 = board.get(d5)
				piece6 = board.get(g6)
				if piece1 != -1:
					game.move('Ng1-f3')
					game.advance()
					return 1
				elif piece2 != -1:
					game.move('Pd2-d4')
					game.advance()
					return 1
				elif piece3 != -1:
					game.move('Ng1-f3')
					game.advance()
					return 1
				elif piece4 != -1:
					game.move('Pd2-d4')
					game.advance()
					return 1
				elif piece5 != -1:
					game.move('e4xd5')
					game.advance()
					return 1
				elif piece6 != -1:
					game.move('Pd2-d4')
					game.advance()
					return 1				
				else:	
					return 0				
	else:
		return 0					
def hungoppositionsquaresbetter():
	hungsquares = []
	for i in range(0,8):
		for j in range(0,8):
			square = cols[i] + rows[j]
			myattacks = defense(square)
			theirdefense = threats(square)
			loc = chess.AlgebraicLoc(square)
			piece = board.get(loc)
			if piece != -1:
				if piece.symbol[0] != 'K' and colourat(square) == othercolour:
					if len(myattacks) >= len(theirdefense) -1:
						hungsquares.append(square)
	return hungsquares					
def attacksquaresforpawns():
	hungsquares = []
	for i in range(0,8):
		for j in range(0,8):
			square = cols[i] + rows[j]
			myattacks = defense(square)
			loc = chess.AlgebraicLoc(square)
			piece = board.get(loc)
			if piece != -1:
				if piece.symbol[0] != 'K' and colourat(square) == othercolour:
					hungsquares.append(square)
	return hungsquares				
def hungoppositionsquaresother():
	hungsquares = []
	for i in range(0,8):
		for j in range(0,8):
			square = cols[i] + rows[j]
			myattacks = defense(square)
			theirdefense = threats(square)
			loc = chess.AlgebraicLoc(square)
			piece = board.get(loc)
			if piece != -1:
				if piece.symbol[0] != 'K' and colourat(square) == othercolour:
					if len(myattacks) >= len(theirdefense) -1:
						hungsquares.append(square)
	return hungsquares						
def evaluate(testmove):
	global board
	def defenseh(square,localboard):
		defs = []
		loc = chess.AlgebraicLoc(square)
		defenses = localboard.threat(loc,othercolour)
		return len(defenses)
	def threatsh(square,localboard):
		defs = []
		loc = chess.AlgebraicLoc(square)
		defenses = localboard.threat(loc,mycolour)
		return len(defenses)	
	cloneboard1 = board.clone()
	def lcolourat(square):
		loc = chess.AlgebraicLoc(square)
		piece = cloneboard1.get(loc)
		if piece != -1:
			return piece.color
		else:
			return -1	
	#intialize variables
	totalvalue = 0
	controlledsquare = 10
	controlledcentersquare = 25
	pieceoncentersquare = 1
	centralmove = 2
	clonegame1 = chess.Game(None,None)
	clonegame1.turn = mycolour
	clonegame1.board = cloneboard1
	startsquare = testmove[1] + testmove[2]
	endsquare = testmove[4] + testmove[5]
	endthreats = threatsh(endsquare,cloneboard1)
	enddefense = defenseh(endsquare,cloneboard1)
	mypieceloc = chess.AlgebraicLoc(startsquare)
	mypiece = cloneboard1.get(mypieceloc)
	endloc = chess.AlgebraicLoc(endsquare)
	endpiece = cloneboard1.get(endloc)
	e4threats = threatsh('e4',cloneboard1)
	e5threats = threatsh('e5',cloneboard1)
	d4threats = threatsh('d4',cloneboard1)
	d5threats = threatsh('d5',cloneboard1)
	if endpiece != -1:
		if mypiece.symbol[0] == 'P':
			totalvalue += endpiece.quality
		else:
			if endthreats < enddefense:
				totalvalue += endpiece.quality - mypiece.quality
			else:
				totalvalue -= mypiece.quality	
	if turncount < 6:
		if endsquare[0] == 'c' or endsquare[0] == 'd' or endsquare[0] == 'e' or endsquare[0] == 'f':
			totalvalue += centralmove
	#special queen functions
	if mypiece.symbol[0] == 'Q':
		if endthreats > 0:
			print endthreats
			print "THREATS"
			totalvalue -= 9000000000
		if turncount < 6:
			totalvalue -= 90000	
	#piece on center square bonus		
	#print endsquare
	if endsquare == 'e5' or endsquare == 'd5' or endsquare == 'd4' or endsquare == 'e4':
		#print 'here'
		totalvalue += pieceoncentersquare
		if endthreats < enddefense:
			totalvalue += controlledcentersquare
		
	#threat calculations
	if endthreats < enddefense:
		if endpiece != -1:
			if endpiece.quality >= mypiece.quality:
				if endthreats-1 > 0:
					totalvalue += endpiece.quailty - mypiece.quality
				else:
					totalvalue += endpiece.quality
			else:
				if endthreats-1 == 0:
					totalvalue += endpiece.quality
				else:
					totalvalue -= mypiece.quality			
	else:
		if endpiece != -1:
			f = mypiece.quality * 1.2
			if endpiece.quality > f:
				totalvalue += endpiece.quality - mypiece.quality										
		else:
			totalvalue -= mypiece.quality
			
	#calculate weather moving into defended
	if endthreats < enddefense:
		totalvalue += controlledsquare
	#make move
	clonegame1.move(testmove)
	clonegame1.advance()
	#if checkmated best move evar!
	if clonegame1.ok() != True:
		totalvalue += 100000000000
	#center square values
	for i in range(0,8):
		for j in range(0,8):
			square = cols[j] + rows[i]					
			sloc = chess.AlgebraicLoc(square)
			spiece = cloneboard1.get(sloc)
			sdef = defenseh(square,cloneboard1)
			sthr = threatsh(square,cloneboard1)	
			if square == 'e4' or square == 'd4' or square == 'd5' or square == 'e5':
				#print sdef
				#print sthr
				if sdef-1 > sthr:
					print "here"
					print testmove
					totalvalue += controlledcentersquare
			else:
				#print sdef
				#print sthr
				if sdef > sthr:
					totalvalue += controlledsquare
				elif sdef < sthr:
					totalvalue -= controlledsquare
			if spiece != -1:
				if lcolourat(square) == mycolour:
					totalvalue += spiece.quality
				elif lcolourat(square) == othercolour:
					totalvalue -= spiece.quality								
			#prevent the queen from moving into threatened squares		
			if spiece != -1:
				if spiece.symbol[0] == 'Q':
					if sthr > 0:
					
						print "HUNG QUEEN"
						print "HUNG QUEEN"
						
						totalvalue -= 10**7
				
						
	return totalvalue		
def ponder():
	global haspondered
	if opening() != 1:
		haspondered = 1
		print haspondered
		possibleattacks = hungoppositionsquaresbetter()
		possibleotherattacks = hungoppositionsquaresother()
		possiblepawnattacks = attacksquaresforpawns()
		print possibleattacks
		print "one not returned"
		moves = mypeicespossible()
		tmpvalue = 0
		bestmove_value = -900000000
		bestmove_move = ''
		for j in range(0,len(moves)):
			for k in range(0,len(moves[j][1])):
				tmpmove = moves[j][0] + '-' + moves[j][1][k]
				tmpvalue = evaluate(tmpmove)
				if tmpvalue > bestmove_value:
					bestmove_value = tmpvalue
					bestmove_move = tmpmove
		if game.turn == mycolour:
			print bestmove_move
			game.move(bestmove_move)
			game.advance()			
def queensgambit():
	global turncount
	if turncount == 0:
		game.move('Pd7-d5')
		return 1
	elif turncount == 1:
		game.move('Pe7-e6')
		return 1
		
	else:
		return 0
print "This program is licensed under the GPL"
print "Read the file COPYING for the full license"
print "This program was written by Sam Phippen <samphippen@gmail.com>"
print "The library used to validate chess moves was"
print "Originally written by Erik Max Francis <max@alcyone.com>"
print "And was modified by Sam Phippen <samphippen@gmail.com>"
turncount = 0				
openingflag = -1
while game.ok():
	if game.turn == mycolour:
		print "pondering"
		ponder()				
		#game.move(possmoves[j][0] + '-' + possmoves[j][1][k])
		if mycolour == 1:
			turncount = turncount +1
	for line in game.show():
		print line
	command = raw_input()
	words = string.split(command)
	try: 
		if len(words) == 2 and words[0] == 'move':
			move = game.move(words[1])
			print "%s moves %s" % \
				(chess.COLORS[game.turn], move.longAlgebraic())
			if move.capture:
				print "%s takes %s" % (move.piece.name, move.capture.name)
			for line in game.show():
				print line
			game.advance()
			if mycolour == 0:
				turncount = turncount +1
		for line in game.show():
			print line
	except chess.Error, e:
		print str(e)
